package com.ec.edu.server.hello;

import com.ec.edu.common.decoder.MsgPackDecoder;
import com.ec.edu.common.encoder.MsgPackEncoder;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;

/**
 * chanel注册后会执行里面相应的初始化方法(也就是将handler逐个进行添加)
 */
public class HelloNettyServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {

        //对chanel进行初始化
        //通过socketChannel去获得对应的管道
        ChannelPipeline channelPipeline = socketChannel.pipeline();
        /**
         * pipeline中会有很多handler类（也称之拦截器类）
         * 获得pipeline之后，可以直接.add，添加不管是自己开发的handler还是netty提供的handler
         */

        toHttp(channelPipeline);

//        toMsgPac(channelPipeline);

    }


    /**
     * TODO 以下针对Http编码
     * @param pipeline
     */
    private void toHttp(ChannelPipeline pipeline) {
        //一般来讲添加到last即可，添加了一个handler并且取名为HttpServerCodec
        //当请求到达服务端，要做解码，响应到客户端做编码
        pipeline.addLast("httpServerCodec", new HttpServerCodec());
        pipeline.addLast(new ChunkedWriteHandler());
        //将请求转换为单一的 FullHttpReques
        pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
        // ====================== 增加心跳支持 start    ======================
        // 针对客户端，如果在1分钟时没有向服务端发送读写心跳(ALL)，则主动断开
        // 如果是读空闲或者写空闲，不处理
        pipeline.addLast(new IdleStateHandler(8, 10, 12));
        // 自定义的空闲状态检测
        pipeline.addLast(new HeartBeatHandler());
        // ====================== 增加心跳支持 end    ======================

        //浏览器请求时 ws://localhost:8888/ws 表示请求的uri
        //WebSocketServerProtocolHandler 核心功能是将 http协议升级为 ws协议 , 保持长连接
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        pipeline.addLast(new HttpServerHandler());
    }

    /**
     * TODO 以下针对MsgPac编码
     * @param channelPipeline
     */
    private void toMsgPac(ChannelPipeline channelPipeline) {
        //首先加入LengthFieldBasedFrameDecoder解码器，解决tcp粘包和拆包的问题
        channelPipeline.addLast("frameDecoder",
                new LengthFieldBasedFrameDecoder(65535, 0,2,0,2));
        //加入MessagePackDcoder
        channelPipeline.addLast("msgPack decoder", new MsgPackDecoder());
        //加入LengthFieldPrepender编码器，解决tcp粘包和拆包的问题
        channelPipeline.addLast("frameEncoder", new LengthFieldPrepender(2));
        //加入MessagePackEncoder
        channelPipeline.addLast("msgPack encoder", new MsgPackEncoder());
        //添加自定义的CustomHandler这个handler，返回Hello Netty
        channelPipeline.addLast("serverHandler", new MsgPackServerHandler());

    }
}
